package models;

import global.ConfigData;

import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import lib.Field;
import lib.persistence.NotFoundException;
import lib.persistence.commands.GetRow;


public class Event extends ModelAbstract implements Serializable
{
	// Subject to change. I set it up so that we have something in place. Enums enforce strong typing.
	public enum Status {Complete, Canceled, Postponed}

	// Private members based on the excel file that was written.

	private int eventId;
	private String name;
	private Date eventDate;
	private String additionalNotes;
	private List<Person> actors;
	private Status status;
	private String location;
	private Person creator;
	private Project project;
	public Event()
	{
	}

	public Event(String name, Date date, String event_Description, List<Person> actors, 
			Status status, String location, Person creator) throws SQLException 
	{
	    this(-1, name, date, event_Description, actors, status,
		    location, creator);
	}

	public Event(int eventId, String name, Date date, String event_Description, 
			List<Person> actors, Status status, String location, Person creator) throws SQLException 
	{
		super();
		this.name = name;
		additionalNotes = event_Description;
		this.eventDate = date;
		this.status = status;
		this.location = location;
		if (actors != null)
			setActors(actors);

		if (creator != null)
			this.setCreator(creator);

	}

	//Getters and Setters

	public List<Person> getActors() {
		return actors;
	}

	public void setActors(List<Person> actors) {

		if (actors == null)
		{
			this.actors = null;
		}

		else {
			Iterator<Person> actIterator = actors.iterator();
			this.actors = new ArrayList<Person>(actors.size());

			while(actIterator.hasNext())
			{
				this.actors.add(actIterator.next());
			}
		}
	}

	public Status getStatus() {
		return status;
	}

	public void setStatus(Status status) {
		this.status = status;
	}
	public void setStatus(String status) {
		this.status = Status.valueOf(status);
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}

	public String getEventName() 
	{
		return name;
	}
	
	/**
	 * @return the eventId
	 */
	public int getEventId() {
	    return eventId;
	}

	public void setEventName(String event_Name) 
	{
		name = event_Name;
	}

	public void setEventDate (Date date)
	{
		this.eventDate = date;
	}
	
	/**
	 * @param eventId the eventId to set
	 */
	public void setEventId(int eventId) {
	    this.eventId = eventId;
	}
	
	public Date getEventDate()
	{
		return eventDate;
	}

	public String getAdditionalNotes() 
	{
		return additionalNotes;
	}

	public void setAdditionalNotes(String event_Description) 
	{
		additionalNotes = event_Description;
	}

	// End getters and setters

	public boolean equals (Event o)
	{
		if (this.creator != null)
		{
			if (!this.creator.equals(o.creator))
				return false;
		}
		if (!this.eventDate.equals(o.eventDate))
			return false;
		if (!o.getAdditionalNotes().equals(additionalNotes))
			return false;
		if (!name.equals(o.getEventName()))
			return false;
		
		if (!o.location.equals(location))
			return false;
		if (o.getStatus() != status)
			return false;

		// Assumes that the list is ordered in the same way. 

		if (o.getActors() != null && actors !=null)
		{
			Iterator<Person> thisIterator = actors.iterator();
			Iterator<Person> oIterator = o.getActors().iterator();

			while (thisIterator.hasNext() && oIterator.hasNext())
			{
				Person p1 = thisIterator.next();
				Person p2 = oIterator.next();
				if (!p1.equals(p2))
					return false;
			}

			if (thisIterator.hasNext() || oIterator.hasNext())
				return false; 	// would indicate that one list is longer than the other.
		}
		else 
			if (this.actors != null || o.actors != null)
				return false;

		return true;
	}

	public void setCreator(Person creator) throws SQLException {
		System.out.println(creator.getId());
		if (creator.id != -1)
			creator.create();
		this.creator = creator;
	}

	public Person getCreator() {
		return creator;
	}

	@Override
	public int getId() {
		return id;
	}

	@Override
	protected ArrayList<Field> getSqlReadyFields() {
		ArrayList<Field> al = new ArrayList<Field>();
		Field f;
		
		// blob
		f = new Field();
		al.add(f.setName("obj").setType("blob").setObjValue(this));

		// name
		f = new Field();
		al.add(f.setName("name").setType("string").setValue(this.name));

		// date

		f = new Field();
		al.add(f.setName("eventdate").setType("date").setObjValue(this.eventDate));
		

		// status 
		f = new Field();
		al.add(f.setName("status").setType("string").setValue(this.status.toString()));
		
		// location
		f = new Field();
		al.add(f.setName("location").setType("string").setValue(this.location));

		//add creator
		if (creator != null)
		{		
			f = new Field();
			al.add(f.setName("createdBy").setType("integer").setValue("" + creator.getId()));
		}
		//add project
		if (this.project!= null)
		{		
			f = new Field();
			al.add(f.setName("project_id").setType("integer").setValue("" + project.getId()));
		}
		String actorIds = "";
		for (int i = 0 ; i < actors.size() ; i++)
		{
			actorIds = actorIds.concat(""+actors.get(i).getId());
			if (i < actors.size() - 1)
				actorIds = actorIds.concat(",");
		}
	    f = new Field();
	    al.add(f.setName("actor_ids").setType("string").setValue(actorIds));
		
	    return al;
	}

	@Override
	protected String getTableName() {
		return ConfigData.EVENT_TABLE;
	}

	@Override
	public void setId(int id) {
		this.id = id;
	}
	public void setId(String id)
	{
		setId(Integer.parseInt(id));
	}

	public static Event find(int id) throws NotFoundException, IOException, ClassNotFoundException, SQLException   
	{
		GetRow gr = new GetRow();
		Event e = (Event) gr.findObjectById(id, ConfigData.EVENT_TABLE , "obj");
		
		int personId = gr.findIntById(id, ConfigData.EVENT_TABLE, "id");
		// some primitive object-relational mapping
		e.setCreator((Person) gr.findObjectById(personId, ConfigData.PERSON_TABLE, "obj"));
		
		int projectId = gr.findIntById(id, ConfigData.EVENT_TABLE, "id");
		e.setProject((Project) gr.findObjectById(projectId, ConfigData.PROJECT_TABLE,"obj"));
		
		String actorIds = (String) gr.findObjectById(id, ConfigData.EVENT_TABLE, "ActorIds");
		e.setActorIds(actorIds);
		
		return e;
	}
	
	public static Event findLatest() throws SQLException, IOException, NotFoundException, ClassNotFoundException {
		GetRow gr = new GetRow();
		ArrayList<Object>  set = gr.findObjectsByLatest(1,"id DESC", ConfigData.EVENT_TABLE ,"obj");
		Event e = (Event) set.get(0);
		
		int personId = gr.findIntById(e.id, ConfigData.EVENT_TABLE, "person_id");
		// some primitive object-relational mapping
		e.setCreator((Person) gr.findObjectById(personId , ConfigData.PERSON_TABLE, "obj"));
		
		int projectId = gr.findIntById(e.id, ConfigData.EVENT_TABLE, "project_id");
		e.setProject((Project) gr.findObjectById(projectId, ConfigData.PROJECT_TABLE, "obj"));
		
		String actorIds = (String) gr.findObjectById(e.id, ConfigData.EVENT_TABLE, "ActorIds");
		e.setActorIds(actorIds);
		
		return e;
	}
	
    public void setProjectId(String project_id) {
    	try {
			setProject(Project.find(Integer.parseInt(project_id)));
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
	public void setActorIds(String actorIds)
	{
		if (actorIds == null || actorIds.equalsIgnoreCase(""))
			return;
		List<Person> actors = new ArrayList<Person>();
        String[] splitArray = actorIds.split("\\,");
        for (String id: splitArray) {
        	try {
				Person p = Person.find(Integer.parseInt(id));
				actors.add(p);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
        this.actors = (ArrayList<Person>) actors;
	}
	
	public void setProject(Project project) {
		this.project = project;
	}

	public Project getProject() {
		return project;
	}
	
	public void setEventDate(String eventDate) {
		SimpleDateFormat d = new SimpleDateFormat("MM/dd/yy");
		try {
			this.eventDate = d.parse(eventDate);
		} catch (ParseException e) {
		}

	}

}
